/******************************************************************************
 * Include files
 ******************************************************************************/
#include "stdio.h"
#include "main.h"
#include "cw32l010_sysctrl.h"
#include "cw32l010_systick.h"
#include "bsp_flash.h"
#include "bsp_adc.h"
#include "bsp_rtc.h"
#include "bsp_tim.h"
#include "bsp_uart.h"
#include "bsp_gpio.h"
#include "bsp_4g_task.h"
#include "bsp_4g_common.h"
#include "DefultParameter.h"

#if PRINT_DEBUG
#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define PRINTF(fmt, ...)
#endif

uint16_t net_led_tick = 0;

// 在这里处理LED相关的一些东西
void bsp_userTips_handler()
{
	static int rrr = 0;
	if (rrr++ >= 100)
	{
		rrr = 0;
		printf("systick.\r\n");
	}
	// if (DEVICE_GET_DI_STATE())
	{
		ALARM_LED_ON();
	}

	if (driver_4Gmoudle_net_connecting() == 1 && net_led_tick == 0)
	{
		net_led_tick = 1000;
	}

	if (driver_4Gmoudle_netsta() == 1 || net_led_tick)
	{
		if (driver_4Gmoudle_data_trans_sta() == 1)
		{
			net_led_tick = 500;
		}

		if (net_led_tick)
			net_led_tick--;

		if (net_led_tick % 100 == 0 && net_led_tick > 0)
		{
			NET_LED_TOG();
		}
		else
		{
			NET_LED_ON();
		}
	}
	else
	{
		NET_LED_OFF();
	}
}

void SysTick_Handler(void)
{
	/* USER CODE BEGIN SysTick_IRQn */
	uwTick += uwTickFreq;
	bsp_userTips_handler();
	/* USER CODE END SysTick_IRQn */
}

void bsp_closeAllPeriphCLK(void) // 关闭所有外设，进入低功耗模式
{
	/*注意：在进入深度休眠模式之前，若FLASH正在进行擦写操作，则必须等待FLASH_ISR.BUSY标志位清0，同时须确保FLASH_CR1.MODE为0。*/
	while (CW_FLASH->ISR_f.BUSY != 0 || CW_FLASH->CR1_f.MODE != 0)
	{
	};

#if 0
	CW_SYSCTRL->APBEN1 = 0x5a5a0000;
	CW_SYSCTRL->APBEN2 = 0x5a5a0000;
	CW_SYSCTRL->AHBEN  = 0x5a5a0000;
	
	__SYSCTRL_RTC_CLK_ENABLE();

#else
	PA01_AFx_GPIO();

	ALARM_LED_OFF();
	NET_LED_OFF();

	GPIO_WritePin(CW_GPIOA, GPIO_PIN_1, GPIO_Pin_RESET);

	// GPIO_DeInit(CW_GPIOA, GPIO_PIN_All);
	// GPIO_DeInit(CW_GPIOB, GPIO_PIN_All);

	SYSCTRL_APBPeriphReset1(SYSCTRL_APB1_PERIPH_UART1, ENABLE);
	SYSCTRL_APBPeriphReset1(SYSCTRL_APB1_PERIPH_UART1, DISABLE);
	SYSCTRL_APBPeriphReset1(SYSCTRL_APB1_PERIPH_UART2, ENABLE);
	SYSCTRL_APBPeriphReset1(SYSCTRL_APB1_PERIPH_UART2, DISABLE);

	SYSCTRL_APBPeriphReset1(SYSCTRL_APB1_PERIPH_ADC, ENABLE);
	SYSCTRL_APBPeriphReset1(SYSCTRL_APB1_PERIPH_ADC, DISABLE);

	//	SYSCTRL_AHBPeriphReset(SYSCTRL_AHB_PERIPH_GPIOA, ENABLE);
	//	SYSCTRL_AHBPeriphReset(SYSCTRL_AHB_PERIPH_GPIOA, DISABLE);

	SYSCTRL_AHBPeriphReset(SYSCTRL_AHB_PERIPH_GPIOB, ENABLE);
	SYSCTRL_AHBPeriphReset(SYSCTRL_AHB_PERIPH_GPIOB, DISABLE);

	SYSCTRL_AHBPeriphClk_Enable(SYSCTRL_AHB_PERIPH_GPIOA, DISABLE);
	SYSCTRL_AHBPeriphClk_Enable(SYSCTRL_AHB_PERIPH_GPIOB, DISABLE);
	SYSCTRL_APBPeriphClk_Enable1(SYSCTRL_APB1_PERIPH_ADC, DISABLE);
	SYSCTRL_APBPeriphClk_Enable1(SYSCTRL_APB1_PERIPH_UART1, DISABLE);
	SYSCTRL_APBPeriphClk_Enable1(SYSCTRL_APB1_PERIPH_UART2, DISABLE);

	SuspendTick();
#endif

	//	切换内核时钟到LSI后功耗反而升高，原因未知
	//	if( SYSCTRL_SysClk_Switch( SYSCTRL_SYSCLKSRC_LSI ) == 0x00 )   //切换系统时钟到LSI
	//	{
	//		SYSCTRL_HSI_Disable();  //切换时钟后关闭源时钟HSI
	//	}
}

int32_t main(void)
{
	SYSCTRL_LSI_Enable();
	SYSCTRL_HSI_Enable(SYSCTRL_HSIOSC_DIV12); // 设置系统为4Mhz
	SYSCTRL_SysClk_Switch(SYSCTRL_SYSCLKSRC_HSI);
	InitTick(SystemCoreClock);

	bsp_flash_init(); // PCLK
	bsp_rtc_init();	  // LSI
	bsp_gpio_init();
	//  bsp_basicTimer_init();
	extern int driver_4Gmoudle_init(driver_4g_para_t * para);
	extern int Device_4G_Task(unsigned short para);

	driver_4g_para_t para_4g = {
		.rec_cache_length = 512,
		.rec_cache_num = 1,
		.send_cache_length = 512};

	driver_4Gmoudle_init(&para_4g);

	if (BSP_FLASH_READ_WORD(DEVICE_SN_CHECK_ADDR) == 0XFFFFFFFF) // 生产模式标志， 从flash加载指定位置是否为0xffffffff
	{
		bsp_uart_init();
		bsp_adc_init();
		device_sn_t *sn = (device_sn_t *)(DEVICE_SN_CHECK_ADDR);
		while (1)
		{
			device_factory_test();
			if (sn->factory_sucess_mark == FACTORY_MARK)
			{
				int ret = Device_4G_Task(get_adc_value());
				printf("4g_ret:%d\r\n", ret);
				while (1)
				{
				};
			}
		}
	}

	/*将SLEEPONEXIT位置1，当退出最低优先级的中断服务程序后，MCU会进入休眠模式（SLEEPDEEP为0时）
		或深度休眠模式（SLEEPDEEP为1时），而不需执行WFI指令	。*/
	// SYSCTRL_ConfigSleepOnExit(DISABLE); //使能这个所有任务就必须在中断函数中执行，因为退出中断后系统自动进入低功耗状态，不会执行while(1)中的函数

	/*休眠模式下，CPU停止运行，所有外设保持运行，包括ARM®	Cortex®-M0+内核外设，比如NVIC、SysTick等外设。
		休眠模式的功耗低于运行模式。*/
	// SYSCTRL_GotoSleep();

	/*深度休眠模式下，CPU停止运行，高速时钟关闭，低速时钟保持状态不变，部分外设可以配置为继续运行，NVIC
			中断处理仍然工作。深度休眠模式的功耗远小于休眠模式。*/
	// SYSCTRL_GotoDeepSleep();
	int8_t ret = 0;
	uint8_t sys_restore_cnt = 0;
	while (1)
	{
		SYSCTRL_HSI_Enable(SYSCTRL_HSIOSC_DIV12); // 设置系统为4Mhz
		SYSCTRL_SysClk_Switch(SYSCTRL_SYSCLKSRC_HSI);
		bsp_gpio_init();

#if PRINT_DEBUG
		bsp_uart_init();
#endif
		bsp_adc_init();
		ResumeTick(); // 恢复systick
		SysTickDelay(1000);
		while ((ret = Device_4G_Task(get_adc_value())) > 0)
		{
		};
		if (ret == 0)
		{
			PRINTF("success!\r\n");
			bsp_setRTC_Close(); // 成功之后就不用唤醒了
		}
		else
		{
			sys_restore_cnt++;
			if (sys_restore_cnt < (3 * 20)) // 要求失败后总计上报这么多次
			{
				if ((sys_restore_cnt % 3) != 0) // 唤醒的三次内， 延时一分钟
				{
					PRINTF("error delay Minute.\r\n");
					bsp_setRTC_AutoWakeup(60);
					// bsp_setRTC_AlarmTime(0xff, RTC_TimeStruct.Minute + 1, RTC_TimeStruct.Second);
				}
				else
				{ // 三次都失败 ，延时一小时
					PRINTF("error delay Hour.\r\n");
					bsp_setRTC_AutoWakeup(60 * 60);
					// bsp_setRTC_AlarmTime(RTC_TimeStruct.Hour + 1, RTC_TimeStruct.Minute, RTC_TimeStruct.Second);
				}
			}
			else
			{ // 报不上去 开摆
				PRINTF("over limit error %d.\r\n", sys_restore_cnt);
				bsp_setRTC_Close();
			}
		}
		bsp_closeAllPeriphCLK();
		SYSCTRL_GotoDeepSleep();
	}
}

/******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
#ifdef USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
	/* USER CODE BEGIN 6 */
	/* User can add his own implementation to report the file name and line number,
	   tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
	/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
